#ifndef REALGEN_CUH
#define REALGEN_CUH

/****************** Representacion real ********************/

/******************* Declaracion de Funciones del Host *************************/
void representacionRealGen();
void traerImprimirRealGen(float* fitnessHost, float* fitnessDevice, int tamVectorFitnessFloat, float* poblacionHost, float* poblacionDevice, int tamVectorPoblacion, int iteracion);

/******************* Declaracion de Funciones Global del Device ********************/
__global__ void inicializarPoblacionRealGen(float* poblacion, float* fitnessActualDevice, struct Random randomGPU, int cantCromosomasPoblacion, float* fitnessOrdenadoDevice);
__global__ void mainKernelRealGen(float* poblacionActualDevice, float* nuevaPoblacionDevice, float* fitnessActualDevice, float* nuevoFitnessDevice, int* poblacionActualAcambiarDevice, int*  nuevaPoblacionAcambiarDevice, float* individuosAMigrarDevice, float * probabilidadRuletaDevice, float * fitnessTotalParaRuletaDevice, struct Random r, int generacionActual, float * individuoAMigrarGPUaCPUdevice, float* fitnessOrdenadoDevice, int* vectorIndicesFitnessOrdenado);

__global__ void asignarProbabilidadRuletaRealGen(float* fitnessActualDevice, float* probabilidadRuletaReal, float* fitnessTotalParaRuletaDevice, struct Random randomGPU);

__global__ void migracionRepresentacionRealGen(float* poblacionActualDevice, float* fitnessActualDevice, float* individuosAMigrarDevice, float* fitnessAMigrarDevice, struct Random randomGPU, float* individuoAMigrarCPUaGPUdevice, float* fitnessAMigrarCPUaGPUdevice);
__global__ void individuosAMigrarRepresentacionRealGen(float* nuevoFitnessDevice, float* nuevaPoblacionDevice, float* individuosAMigrarDevice, float* fitnessAMigrarDevice, float * individuoAMigrarGPUaCPUdevice);

__global__ void reemplazoElitistaSeleccionIndividuosRealGen(float* poblacionActual, float* nuevaPoblacion, int* poblacionActualAcambiar, int* nuevaPoblacionAcambiar, float * fitnessActual, float* nuevoFitness, int * posIndAreemplazarViejosElitistaGPU, int * posIndAreemplazarNuevosElitistaGPU);
__global__ void reemplazoRealGen(float * poblacionActualDevice, float * nuevaPoblacionDevice, int * posIndAreemplazarViejosElitistaGPU, int * posIndAreemplazarNuevosElitistaGPU);

__global__ void obtenerMejoresIndividuosRealGen(float* poblacion, float* fitness, float* mejorIndividuoDevice, float* mejorFitnessIndividuoGPUDevice);

__global__ void asignarFitnessRealGen(float* poblacion, float* vectorFitness, float* fitnessOrdenadoDevice);

/******************* Declaracion de Funciones internas del Device *****************/
__device__ void obtenerMejorIndividuoRealGen(float* vectorFitnesss, int indices[2]);
__device__ void obtenerPeorIndividuoRealGen(float* vectorFitness, int indices[2]);

__device__ int seleccionRealGen(float* vectorFitness, float* probabilidadRuletaDevice, struct Random randomGPU, int ejecutarFuncion, int* vectorIndicesFitnessOrdenado, int nroSeleccion);
__device__ int seleccionPorTorneoRealGen(float* vectorFitness, struct Random randomGPU, int nroSeleccion);
__device__ int seleccionPorRangoRealGen(int* vectorIndicesFitnessOrdenado, struct Random randomGPU, int nroSeleccion);
__device__ int seleccionRuedaRuletaRealGen(float* probabilidadRuletaDevice, struct Random randomGPU, int nroSeleccion);

__device__ void cruzamientoRepresentacionRealGen(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU, int ejecutarFuncion);
__device__ void cruzamientoAritmeticoIndividualGen(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU);
__device__ void cruzamientoAritmeticoSimpleGen(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU);
__device__ void cruzamientoAritmeticoCompletoGen(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU);

__device__ void mutacionRealGen(float* poblacion, float probabilidad, struct Random randomGPU, int ejecutarFuncion, int generacionActual);
__device__ void mutacionUniformeGen(float* poblacion, float probabilidad, struct Random randomGPU);
__device__ void mutacionNoUniformeGen(float* poblacion, float probabilidad, struct Random randomGPU, int generacionActual);

__device__ void reemplazoElitistaRealGen(float* poblacionActual, float* nuevaPoblacion, int * posIndAreemplazarViejosElitistaGPU, int * posIndAreemplazarNuevosElitistaGPU);

#endif
